package com.dy.design_pattern_study.interpreter_pattern.dome2;

import com.dy.design_pattern_study.interpreter_pattern.dome2.impl.Note;
import com.dy.design_pattern_study.interpreter_pattern.dome2.impl.Scale;
import com.dy.design_pattern_study.interpreter_pattern.dome2.impl.Speed;
import com.dy.design_pattern_study.utils.Utils;

/**
 * @CreateBy zhangdingyi
 * @Date 2023-04-24
 * @Content 解释器模式（interpreter），给定一个语言，定义它的文法的一种表示，并定义一个解释器，这个解释器使用该表示来解释语言中的句子。
 * 简单的说
 * 1.就是把字符串进行解析，不同的字符串有不同的效果，类似 正则表达式、还有编程语言的 解析
 * <p>
 * 2.像IE、Firefox这些浏览器，其实也是在解释HTML文法，将下载到客户端的HTML标记文本转换成网页格式显示到用户
 * <p>
 * 3.解释器模式就是用‘迷你语言’来表现程序要解决的问题，以迷你语言写成‘迷你程序’来表现具体的问题
 * <p>
 * 4.就是可以把某种类或字符串转化成自己想要的结果
 */
public class client {
    /*
        解释器模式可以解决什么问题？
        1.如果一种特定类型的问题发生的频率足够高，那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。
        这样就可以构建一个解释器，该解释器通过解释这些句子来解决该问题

        简单的说：就是制定规则去 转换 特定问题有对应的结果
        例子：就是有一串字符串有不同的字母和数值，制定规则 字母T是 音速、O是 音色、其他字母是 音符，数值是 不同的类型
        然后 具体根据一串字符串 转换成 自己想要的结果解析

        再简单一点：就是把问题单元解析成自己想要转换的目标

        2.解释器模式，正则表达式就是它的一种应用，解释器为正则表达式定义了一个文法，
        如何表示一个特定的正则表达式，以及如何解释这个正则表达式

        3.当有一个语言需要解释执行，并且你可将该语言中的句子表示为一个抽象语法树时，可使用解释器模式

     */

    /*
        解释器模式优缺点
        优点
        容易地改变和扩展文法，因为该模式使用类来表示文法规则，你可使用继承来改变或扩展该文法。
        也比较容易实现文法，因为定义抽象语法树中各个节点的类的实现大体类似，这些类都易于直接编写

        缺点
        解释器模式为文法中的每一条规则至少定义了一个类，因此包含许多规则的文法可能难以管理和维护。
        建议当文法非常复杂时，使用其他的技术如语法分析程序或编译器生成器来处理
     */

    public static void main(String[] args) {
        PlayContext context = new PlayContext();
        System.out.println("music start ....");

        context.setText("T 500 T 1001 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 " +
                "G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ");

        Expression expression = null;

        try {
            while (context.getText().length() > 0) {
                String str = context.getText().substring(0, 1);

                expression = swichUse(expression, str);

                if (expression == null) {
                    continue;
                }
                expression.Interpret(context);
            }
        } catch (Exception e) {
            System.out.println("e.getMessage()); = " + e.getMessage());
        }

    }

    /**
     * Switch调用
     *
     * @param expression
     * @param str
     * @return
     */
    private static Expression swichUse(Expression expression, String str) {
        switch (str) {
            case "O":
                //首字母为 O 时，表达式实例化为音阶
                expression = new Scale();
                break;
            case "T":
                expression = new Speed();
                break;
            case "C":
            case "D":
            case "E":
            case "F":
            case "G":
            case "A":
            case "B":
            case "P":
                //首字母是 CDEFGAB，以及休止符P时，则实例化音符
                expression = new Note();
                break;
        }
        return expression;
    }
}
